package org.example.ims.Service.Order.Impl;

import jakarta.persistence.criteria.Predicate;
import org.example.ims.Entity.Base.Salesman;
import org.example.ims.Entity.Base.Warehouse;
import org.example.ims.Entity.Order.*;
import org.example.ims.Repository.Order.TransferOrderRepository;
import org.example.ims.Service.Base.SalesmanService;
import org.example.ims.Service.Base.WarehouseService;
import org.example.ims.Service.Order.InStockOrderService;
import org.example.ims.Service.Order.OutStockOrderService;
import org.example.ims.Service.Order.TransferDetailService;
import org.example.ims.Service.Order.TransferOrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Optional;

@Service("transferOrderService")
public class TransferOrderServiceImpl implements TransferOrderService {

    @Autowired
    private TransferOrderRepository orderRepository;
    @Autowired
    private TransferDetailService transferDetailService;
    @Autowired
    private SalesmanService salesmanService;
    @Autowired
    private WarehouseService warehouseService;
    @Autowired
    private InStockOrderService inStockOrderService;
    @Autowired
    private OutStockOrderService outStockOrderService;


    @Override
    public TransferOrder createOrder(TransferOrder order) {
        for (TransferDetail detail : order.getDetails()) {
            detail.setOrder(order); // 手动设置外键
        }
        return orderRepository.save(order);
    }

    @Override
    public TransferOrder updateOrder(Integer orderId, TransferOrder updatedOrder) {
        TransferOrder existingOrder = orderRepository.findById(orderId)
                .orElseThrow(() -> new NoSuchElementException("TransferOrder not found with id: " + orderId));
        // 清除旧的details
        existingOrder.getDetails().clear();
        // 添加新的details
        for (TransferDetail detail : updatedOrder.getDetails()) {
            detail.setOrder(existingOrder); // 确保设置新的order
            existingOrder.getDetails().add(detail);
        }
        // 保存更新后的order
        return orderRepository.save(existingOrder);
    }

    @Override
    public void deleteOrder(Integer orderId) {
        if (!orderRepository.existsById(orderId)) {
            throw new NoSuchElementException("TransferOrder does not exist with id: " + orderId);
        }
        orderRepository.deleteById(orderId);
    }

    @Override
    public TransferOrder getOrderById(Integer orderId) {
        return orderRepository.findById(orderId)
                .orElseThrow(() -> new NoSuchElementException("TransferOrder not found with id: " + orderId));
    }

    @Override
    public Page<TransferOrder> getAllOrders(Integer page, Integer size) {
        return orderRepository.findAll(PageRequest.of(page, size));
    }

    @Override
    public Page<TransferOrder> searchOrders(String status,
                                            Integer salesmanId, Integer sourceWarehouseId, Integer targetWarehouseId,
                                            Integer page, Integer size) {
        Specification<TransferOrder> specification = buildSpecification(status, salesmanId, sourceWarehouseId, targetWarehouseId);
        return orderRepository.findAll(specification, PageRequest.of(page, size));
    }

    @Override
    public void executeOrder(Integer orderId) {
        try {
            // 根据订单ID获取订单信息，如果不存在则抛出异常
            TransferOrder order = orderRepository.findById(orderId)
                    .orElseThrow(() -> new NoSuchElementException("TransferOrder not found with id: " + orderId));

            // 执行订单有效性验证和库存可行性检查
            //      验证订单相关实体（如仓库）的有效性
             validateRelatedEntities(order);

            // 拆分订单细节，不用验证可行性，分别得到入库订单和对应的订单细节（在系统中创建）
            InStockOrder inStockOrder = InStockOrderBuilder(order);
            OutStockOrder outStockOrder= OutStockOrderBuilder(order);

            // 此时就会出现一个出库订单，一个入库订单,加入数据库中
            InStockOrder exsitingInStockOrder=inStockOrderService.createOrder(inStockOrder);
            OutStockOrder exsitingOutStockOrder=outStockOrderService.createOrder(outStockOrder);
            outStockOrderService.createOrder(outStockOrder);
            // 然后分别调用两者服务执行即可，没有WP层的处理
            inStockOrderService.executeOrder(exsitingInStockOrder.getOrderId());
            outStockOrderService.executeOrder(exsitingOutStockOrder.getOrderId());

            // 更新订单状态为已完成
            order.setStatus("completed");
            orderRepository.save(order);

        } catch (Exception e) {
            // 重新获取订单对象,更改订单状态
            TransferOrder order = orderRepository.findById(orderId)
                    .orElseThrow(() -> new NoSuchElementException("TransferOrder not found with id: " + orderId));
            order.setStatus("failed");
            orderRepository.save(order);
            throw new RuntimeException(e.getMessage());
        }
    }

    // 拆分转仓单并生成对应的入库，出库单
    private InStockOrder InStockOrderBuilder(TransferOrder order) throws Exception {
        InStockOrder inStockOrder = new InStockOrder();
        inStockOrder.setStatus(order.getStatus());
        inStockOrder.setSalesmanId(order.getSalesmanId());
        inStockOrder.setWarehouseId(order.getTargetWarehouseId());
        inStockOrder.setSupplierId(0);
        inStockOrder.setOrderDate(order.getOrderDate());
        inStockOrder.setDetails(transferDetailService
                .convertOrderDetails(order.getDetails(), InStockDetail.class));
        return inStockOrder;
    }

    private OutStockOrder OutStockOrderBuilder(TransferOrder order) throws Exception {
        OutStockOrder outStockOrder= new OutStockOrder();
        outStockOrder.setStatus(order.getStatus());
        outStockOrder.setSalesmanId(order.getSalesmanId());
        outStockOrder.setWarehouseId(order.getTargetWarehouseId());
        outStockOrder.setCustomerId(0);
        outStockOrder.setOrderDate(order.getOrderDate());
        outStockOrder.setDetails(transferDetailService
                .convertOrderDetails(order.getDetails(), OutStockDetail.class));
        return outStockOrder;
    }


    // Build a specification for searching orders
    private Specification<TransferOrder> buildSpecification(String status,
                                                            Integer salesmanId,
                                                            Integer sourceWarehouseId,
                                                            Integer targetWarehouseId) {
        return (root, query, cb) -> {
            List<Predicate> predicates = new ArrayList<>();

            if (status != null) {
                predicates.add(cb.equal(root.get("status"), status));
            }
            if (salesmanId != null) {
                predicates.add(cb.equal(root.get("salesman").get("id"), salesmanId));
            }
            if (sourceWarehouseId != null) {
                predicates.add(cb.equal(root.get("sourceWarehouse").get("id"), sourceWarehouseId));
            }
            if (targetWarehouseId != null) {
                predicates.add(cb.equal(root.get("targetWarehouse").get("id"), targetWarehouseId));
            }

            return cb.and(predicates.toArray(new Predicate[0]));
        };
    }

    // Validate related entities
    private void validateRelatedEntities(TransferOrder order) {
        //判断业务员信息
        if (order.getSalesmanId() != null) {
            Optional<Salesman> salesman = salesmanService.getSalesmanById(order.getSalesmanId());
            if (salesman.isEmpty()) {
                throw new NoSuchElementException("Salesman not found with id: " + order.getSalesmanId());
            }
        }

        //判断源仓库信息
        if (order.getSourceWarehouseId() != null) {
            Optional<Warehouse> warehouse = warehouseService.findWarehouseById(order.getSourceWarehouseId());
            if (warehouse.isEmpty()) {
                throw new NoSuchElementException("Source warehouse not found with id: " + order.getSourceWarehouseId());
            }
        }
        //判断目标仓库信息
        if (order.getTargetWarehouseId() != null) {
            Optional<Warehouse> warehouse = warehouseService.findWarehouseById(order.getTargetWarehouseId());
            if (warehouse.isEmpty()) {
                throw new NoSuchElementException("Target warehouse not found with id: " + order.getTargetWarehouseId());
            }
        }
    }
}